package com.Hermes.User;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;


public class JsonUtil {
    private static String readJsonFile(String fileName) {
        String jsonStr = "";
        try {
            File jsonFile = new File(fileName);
            FileReader fileReader = new FileReader(jsonFile);
            Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8);
            int ch = 0;
            StringBuffer sb = new StringBuffer();
            while ((ch = reader.read()) != -1) {
                sb.append((char) ch);
            }
            fileReader.close();
            reader.close();
            jsonStr = sb.toString();
            return jsonStr;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static ArrayList<node> getNodeList(String fileName, ConcurrentHashMap<Long, Integer> Id2Index, ConcurrentHashMap<Long, Long> inI2I, ConcurrentHashMap<Long, Long> outI2I) {

        ArrayList<node> res = new ArrayList<>();
        String jsonString = readJsonFile(fileName);
        ObjectMapper mapper = new ObjectMapper();
        SecureRandom rng = new SecureRandom(new byte[8]);
        try {
            JsonNode rootNode = mapper.readTree(jsonString);
            Iterator<ConcurrentHashMap.Entry<String, JsonNode>> it = rootNode.fields();
            Iterator<String> tmpIt = rootNode.fieldNames();
            HashSet<String> tmpSet = new HashSet<>();
            tmpIt.forEachRemaining(tmpSet::add);
            double xmax = -1000.0, ymax = -500.0, xmin = 1000.0, ymin = 500.0;
            while (it.hasNext()) {
                JsonNode JSvalue = it.next().getValue();
                JsonNode LON = JSvalue.get("LON");
                double lon = Double.parseDouble(LON.asText());
                xmax = Math.max(xmax, lon);
                xmin = Math.min(xmin, lon);
                JsonNode LAT = JSvalue.get("LAT");
                double lat = Double.parseDouble(LAT.asText());
                ymax = Math.max(ymax, lat);
                ymin = Math.min(ymin, lat);
            }
            double xone = (xmax - xmin) / 1000.0;
            double yone = (ymax - ymin) / 1000.0;
            int index = 0;
            var it1 = rootNode.fields();
            while (it1.hasNext()) {
                long tmp = Long.parseLong(it1.next().getKey());
                Id2Index.put(tmp, index++);
                long tl;
                do{
                    tl = rng.nextLong();
                }while (new BigInteger(String.valueOf(tl)).toByteArray().length!=8);
                inI2I.put(tmp, tl);
                outI2I.put(tl, tmp);
            }
            var it2 = rootNode.fields();
            while (it2.hasNext()) {
                node tmpNode = new node();

                ConcurrentHashMap.Entry<String, JsonNode> next = it2.next();
                if (next.getValue() == null || next.getKey() == null) {
                    break;
                }
                long id = Long.parseLong(next.getKey());
                JsonNode JSvalue = next.getValue();
                if (JSvalue == null) {
                    continue;
                }
                JsonNode LON = JSvalue.get("LON");
                JsonNode LAT = JSvalue.get("LAT");
                JsonNode neighbor = JSvalue.get("Neighbor");
                JsonNode distance = JSvalue.get("Distance");
                double x = Double.parseDouble(LON.asText());
                double y = Double.parseDouble(LAT.asText());
                int xi = (int) ((x - xmin) / xone);
                int yi = (int) ((y - ymin) / yone);

                int len = neighbor.size();

                ArrayList<Integer> tmpd = new ArrayList<>();
                ArrayList<Integer> tmpn = new ArrayList<>();
                for (int i = 0; i < len; i++) {
                    if (!tmpSet.contains(neighbor.get(i).asText())) {
                        continue;
                    }
                    int dis = (int) (Math.ceil(Double.parseDouble(distance.get(i).asText())));
                    tmpd.add(dis);
                    tmpn.add(Id2Index.get(Long.parseLong(neighbor.get(i).asText())));
                }
                tmpNode.Dis = tmpd;
                tmpNode.Neb = tmpn;
                tmpNode.x = xi;
                tmpNode.y = yi;
                tmpNode.id = id;
                tmpNode.index = Id2Index.get(id);
                res.add(tmpNode);
            }


        } catch (JsonProcessingException e) {
            e.printStackTrace();

        }
        return res;

    }

    //    public static ArrayList<tokenNode>getTokens(String fileName){
//        ArrayList<tokenNode>res=new ArrayList<>();
//        return res;
//    }
//    public static ConcurrentHashMap<BigInteger, byte[]>getDX(String fileName){
//
//    }
//    public static  ArrayList<Arr>getArrList(String fileName){
//
//    }
//    //Arr，DX数据转json
//    //json构建Eg
    public static void main(String[] args) {
        long t1 = System.currentTimeMillis();
        ConcurrentHashMap<Long, Integer> i2i = new ConcurrentHashMap<>();
        ConcurrentHashMap<Long, Long> oi2i = new ConcurrentHashMap<>();
        ConcurrentHashMap<Long, Long> ii2i = new ConcurrentHashMap<>();
        ArrayList<node> nodeList = getNodeList("resources/Chicago (2)/ch2200junction.json", i2i,ii2i,oi2i);
        long t2 = System.currentTimeMillis();
        System.out.println("读取数据(t2-t1) = " + (t2 - t1));

    }

//    public static int[][]getGraph(){
//        int[][]res=new int[][];
//        return res;
//    }
}
